Skip to content

FIX: Add custom library build handler to godotcpp.py for chunked object processing to prevent CI/CD from crashing#35

Closed
Arctis-Fireblight wants to merge 5 commits into
Redot-Engine:masterfrom
Arctis-Fireblight:fix-ci-problem
Closed

FIX: Add custom library build handler to godotcpp.py for chunked object processing to prevent CI/CD from crashing#35
Arctis-Fireblight wants to merge 5 commits into
Redot-Engine:masterfrom
Arctis-Fireblight:fix-ci-problem

Conversation

@Arctis-Fireblight
Copy link
Copy Markdown
Contributor

@Arctis-Fireblight Arctis-Fireblight commented May 16, 2026

GitHub Actions runners have a limit of 1024 arguments, which would cause the CI jobs to fail if more 1024 .o files got generated during the build process.

Summary by CodeRabbit

  • New Features

    • Extended GDExtension API with additional version metadata fields and new callback/task typedefs for improved extension and main-loop integration.
  • Chores

    • Improved static library build handling and archival in the build system.
    • Updated CI Windows runners to use a newer Windows image for MSVC and MinGW jobs.
  • Tests

    • Re-enabled and expanded tests to verify internal-class behavior and string representation coverage.

Review Change Stack

…ject processing to prevent CI/CD from crashing

GitHub Actions runners have a limit of 1024 arguments, which would cause the CI jobs to fail if more 1024 `.o` files got generated during the build process.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 16, 2026

📝 Walkthrough

Walkthrough

Adds a chunked static-library archiver integrated into the build; expands GDExtension C API typedefs/structs and converts many comments to Doxygen; updates Windows CI runners to windows-2022; and adds/enables tests asserting internal class behavior.

Changes

GDExtension API and docs updates

Layer / File(s) Summary
GDExtension API and typedef/struct updates
gdextension/gdextension_interface.h
Adds new typedefs (initialize/deinitialize, worker-thread pool task types), extends GDExtensionGodotVersion2 and GDExtensionRedotVersion with additional fields, introduces GDExtensionClassCreationInfo5 alias, adds several exported function-pointer typedefs, updates WorkerThreadPool function-pointer signatures, and converts many comments to Doxygen style.

Custom static library archiving

Layer / File(s) Summary
Custom static library archiving with chunked archiving
tools/godotcpp.py
Adds _godot_cpp_build_library to assemble static archives in 100-item chunks, ensure output directories, remove stale archives, optionally run ranlib, and integrates it into _godot_cpp via env.Command and Action replacing env.StaticLibrary.

CI Windows runner updates

Layer / File(s) Summary
Update Windows runners to windows-2022
.github/workflows/ci-cmake.yml, .github/workflows/ci-scons.yml
Replaces windows-2019 with windows-2022 for Windows matrix entries (MSVC and MinGW/Ninja) in CI workflows.

Test updates

Layer / File(s) Summary
Internal class tests and ExampleMin string assertion
test/project/main.gd
Re-enables ExampleMin to_string() assertion and adds assertions that ExampleInternal is non-instantiable via ClassDB while validating an internal instance returned by the example exposes get_the_answer() == 42 and reports class name "ExampleInternal".

🎯 4 (Complex) | ⏱️ ~45 minutes

🐇 I hopped through headers, builds, and tests,
Chunked up archives and fixed up the rests,
Docs now sing with Doxygen rhyme,
CI updated to newer time,
Internal classes prove their quest.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding a custom library build handler to godotcpp.py for chunked object processing. This directly corresponds to the primary functional change in the PR (the new _godot_cpp_build_library function).
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tools/godotcpp.py`:
- Around line 533-566: Replace the manual POSIX-style command construction using
ar/arflags with SCons' platform-specific archive template: instead of building
cmd = "%s %s %s %s" % (ar, arflags, target_lib, " ".join(chunk)), call env.subst
on env['ARCOM'] (or "$ARCOM") while passing TARGET=target_lib and SOURCES="
".join(chunk) (or SOURCES=chunk as appropriate) to produce the correct platform
command for each chunk, then env.Execute the substituted command/Action; keep
the existing verbose print and the chunking loop around objects/target_lib
unchanged and remove the hardcoded use of ar/arflags/ranlib when invoking the
archive command.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9047d26c-ba94-4ee7-8c9b-008b84b37dee

📥 Commits

Reviewing files that changed from the base of the PR and between e36a8bf and 8b913b9.

📒 Files selected for processing (1)
  • tools/godotcpp.py

Comment thread tools/godotcpp.py Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
test/project/main.gd (1)

293-295: ⚡ Quick win

Add an explicit non-null assertion before calling internal class methods.

This makes failures clearer if internal instance retrieval regresses.

Suggested patch
 	var internal_class = example.test_get_internal_class()
+	assert_not_equal(internal_class, null)
 	assert_equal(internal_class.get_the_answer(), 42)
 	assert_equal(internal_class.get_class(), "ExampleInternal")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/project/main.gd` around lines 293 - 295, The test calls methods on
example.test_get_internal_class() without asserting the returned instance is
non-null; add an explicit non-null assertion for the returned value (e.g.,
assert_not_null or assert_true(internal_class != null)) right after calling
example.test_get_internal_class() so failures clearly indicate a missing
internal instance before invoking internal_class.get_the_answer() and
internal_class.get_class().
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tools/godotcpp.py`:
- Around line 545-554: The chunked archiving loop that builds cmd via
env.subst("$ARCOM", target=target, source=chunk) and calls env.Execute
repeatedly will overwrite MSVC archives because lib.exe /OUT:target replaces the
file each time; update the logic to detect MSVC (e.g. env["is_msvc"] or
equivalent platform flag) and for that case avoid chunking by passing the full
objects list to a single env.subst("$ARCOM", target=target, source=objects) /
single env.Execute call (or use an MSVC-specific incremental strategy), while
keeping the existing chunked path for non-MSVC toolchains; ensure references to
target_lib, objects, env.subst("$ARCOM", ...), and env.Execute are used so you
modify the exact archiving code path.

---

Nitpick comments:
In `@test/project/main.gd`:
- Around line 293-295: The test calls methods on
example.test_get_internal_class() without asserting the returned instance is
non-null; add an explicit non-null assertion for the returned value (e.g.,
assert_not_null or assert_true(internal_class != null)) right after calling
example.test_get_internal_class() so failures clearly indicate a missing
internal instance before invoking internal_class.get_the_answer() and
internal_class.get_class().
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2a618a48-3756-4faf-aeb8-a6ea51444872

📥 Commits

Reviewing files that changed from the base of the PR and between 8b913b9 and bff22d9.

📒 Files selected for processing (6)
  • .github/workflows/ci-cmake.yml
  • .github/workflows/ci-scons.yml
  • gdextension/extension_api.json
  • gdextension/gdextension_interface.h
  • test/project/main.gd
  • tools/godotcpp.py

Comment thread tools/godotcpp.py
Comment on lines +545 to +554
# Process in chunks of 100
for i in range(0, len(objects), 100):
chunk = objects[i : i + 100]
# Use Execute with a substituted $ARCOM to produce the correct platform command for each chunk.
cmd = env.subst("$ARCOM", target=target, source=chunk)
if not env["verbose"]:
print("Archiving %s (chunk %d-%d) ..." % (os.path.basename(str(target_lib)), i, i + len(chunk)))
res = env.Execute(cmd)
if res != 0:
return res
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check which Windows toolchain is configured and whether ARCOM supports incremental archiving

# Check Windows platform tool configuration
echo "=== Windows platform tool configuration ==="
cat tools/windows.py | grep -A 10 -B 5 "ARCOM\|AR\s*=\|lib\.exe" || echo "No explicit ARCOM/AR override found"

# Check CI workflow for toolchain hints
echo ""
echo "=== CI Windows workflow toolchain hints ==="
rg -i "msvc|mingw|clang|visual.studio|compiler" .github/workflows/ --type yaml -C 2 | head -50

# Check if there's any existing handling for MSVC vs MinGW archiving
echo ""
echo "=== Any MSVC-specific archive handling ==="
rg -i "lib\.exe|/OUT:|msvc.*ar" tools/ --type py

Repository: Redot-Engine/redot-cpp

Length of output: 3562


🏁 Script executed:

# Read tools/windows.py to find actual ARCOM configuration
head -200 tools/windows.py | tail -150

# Also check if there's more content about ARCOM
rg -n "ARCOM|AR\s*=" tools/windows.py -A 3 -B 3

Repository: Redot-Engine/redot-cpp

Length of output: 5468


🏁 Script executed:

# Read the full context of the modified godotcpp.py to understand integration
cat -n tools/godotcpp.py | sed -n '530,605p'

Repository: Redot-Engine/redot-cpp

Length of output: 3221


🏁 Script executed:

# Check if the new function is actually being called
rg -n "_godot_cpp_build_library" tools/godotcpp.py

Repository: Redot-Engine/redot-cpp

Length of output: 191


🏁 Script executed:

# Check how many object files are typically compiled
rg -c "add_sources|env.Object" tools/godotcpp.py

# Look for any existing bug reports or comments about MSVC archiving issues
rg -i "msvc.*arch|lib\.exe|chunk.*msvc" . --type py -C 2

# Check if there are any recent changes or comments about this issue
git log --oneline --all --grep="chunk\|archive\|msvc\|windows" -i | head -20

Repository: Redot-Engine/redot-cpp

Length of output: 1492


🏁 Script executed:

# Check the actual line count of sources being added
sed -n '578,585p' tools/godotcpp.py

# Search for any conditional handling of MSVC vs MinGW for archiving
rg -n "is_msvc\|use_mingw" tools/godotcpp.py

Repository: Redot-Engine/redot-cpp

Length of output: 355


🏁 Script executed:

# Count actual source files to see if chunking would be triggered (>100 objects)
find src -name "*.cpp" -type f | wc -l

# Check if there are any error reports or test failures with MSVC builds
git log --all --oneline | grep -i "msvc.*fail\|windows.*fail\|archive" | head -10

# Check if the new _godot_cpp_build_library function has been tested or if there are any known issues
rg -i "godot_cpp_build_library\|chunking\|argument.*limit" . --type md

Repository: Redot-Engine/redot-cpp

Length of output: 69


🏁 Script executed:

# Look for any SCons documentation or examples of how ARCOM should be used with mslib
rg -n "ARCOM\|mslib\|lib.exe" tools/ --type py -B 2 -A 2

# Check if there's any MSVC-specific conditional logic that should be handling this differently
ast-grep --pattern 'if $env["is_msvc"] { $$$ }'

Repository: Redot-Engine/redot-cpp

Length of output: 48


🏁 Script executed:

# Check how many objects would be created and if chunking would actually trigger
# Count cpp files to estimate objects
echo "Source files:"
find src -name "*.cpp" -type f | wc -l
echo ""

# Check if any bindings are generated that would add more objects
rg -n "bindings" tools/godotcpp.py | grep -i "extend\|\.cpp"

# Look for any previous uses of chunking or special MSVC handling in SCons
rg -n "chunk\|ARCOM.*chunk" . --type py

Repository: Redot-Engine/redot-cpp

Length of output: 157


🏁 Script executed:

# Most importantly: check the actual MSVC lib.exe behavior with /OUT: flag
# Look for any SCons documentation comments or tests about this
rg -i "lib\.exe\|/OUT" . --type py -B 2 -A 2

# Check if there's any indication that the library is built incrementally or should be
rg -n "incremental\|append.*archive" . --type py

Repository: Redot-Engine/redot-cpp

Length of output: 48


MSVC archive overwrite issue will corrupt libraries during chunked archiving.

With >100 object files, the chunking loop will execute ARCOM multiple times. On MSVC, lib.exe /OUT:target creates a fresh archive on each invocation rather than appending. This means:

  • Chunk 1: Creates archive with objects 0-99
  • Chunk 2: Overwrites archive with objects 100-199 (losing chunk 1)
  • Chunk N: Final archive contains only the last chunk's objects

MinGW ar r appends correctly, so this only affects MSVC Windows builds, which are tested in the CI matrix.

To fix this for MSVC, either:

  1. Accumulate all objects and pass them in a single ARCOM call (avoiding chunking overhead)
  2. Use platform-specific logic (if env["is_msvc"]) to handle MSVC differently
  3. Use a different archiving strategy for MSVC that supports incremental builds
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/godotcpp.py` around lines 545 - 554, The chunked archiving loop that
builds cmd via env.subst("$ARCOM", target=target, source=chunk) and calls
env.Execute repeatedly will overwrite MSVC archives because lib.exe /OUT:target
replaces the file each time; update the logic to detect MSVC (e.g.
env["is_msvc"] or equivalent platform flag) and for that case avoid chunking by
passing the full objects list to a single env.subst("$ARCOM", target=target,
source=objects) / single env.Execute call (or use an MSVC-specific incremental
strategy), while keeping the existing chunked path for non-MSVC toolchains;
ensure references to target_lib, objects, env.subst("$ARCOM", ...), and
env.Execute are used so you modify the exact archiving code path.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant